function scrollSelect(param){
    let {data, callback, active = []} = param;
    let count = document.querySelectorAll('.scrollSelect').length;
    let selected = [];
    let sizes = {};
    let html = document.createElement('html');
    let styleStr = `<style>.scrollSelect{position:fixed;top:calc(100% - 200px);left:0px;text-align:center;width:100%;height:200px;background-color:white;visibility:hidden;z-index:1;}.scrollSelect .control {height:45px;border-bottom:1px solid #888888;}.scrollSelect .control :first-child{color:black;float:left;margin-left:15px;}.scrollSelect .control :last-child{float:right;color:#ef7f31;margin-right:15px;}.scrollSelect .container{display:flex;overflow:hidden;height:120px;position:relative;top:0;width:100%;padding:0;}.scrollSelect .container hr{position:absolute;width:100%;height:1px;top:20px;background-color:#ef7f31;}.scrollSelect .container > ul{flex-grow:1;position:relative;top:0px;margin:0;padding:0 0 1000px 0;}.scrollSelect .container li{list-style:none;height:20px;padding:5px 0;user-select:none;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;}</style>`;
    html.innerHTML = `<div id="scroll${count}" class="scrollSelect">${count==0?styleStr:''}<div class="control"><p id="cancel">取消</p><p id="select">确定</p></div><div class="container"><hr></div></div>`;
    document.body.appendChild(html.querySelector(`#scroll${count}`));
    let scroll = document.querySelector(`#scroll${count}`);
    let container = scroll.querySelector('.container');
    createUl();
    scroll.querySelector('#cancel').addEventListener('click',function(){
        hide();
    });
    scroll.querySelector('#select').addEventListener('click',function(){
        hide();
        if(typeof callback == 'function') {
            callback(selected.map((v,i)=>getListByDeep(i)[v].value));
        }
    });
    return {
        show, hide
    };
    function createUl(deep = 0) {
        let list = getListByDeep(deep);
        let ul = document.createElement('ul');
        container.appendChild(ul);
        addAnimation(ul, deep);
        let hasChildren = createLi(ul, list, deep);
        setActive(deep, null, active[deep] || '');
        if(hasChildren) {
            createUl(deep + 1);
        }
    }
    function createLi(ul, list, deep) {
        ul.innerHTML = '';
        let hasChildren = false;
        list.forEach((v)=>{
            if(v.children) {
                hasChildren = true;
            }
            let li = document.createElement('li');
            li.appendChild(document.createTextNode(v.text || v.value));
            ul.appendChild(li);
        });
        let height = ul.querySelector('li').offsetHeight;
        let max = 0, min = -height * (list.length - 1);
        min > 0 && (min = 0);
        sizes[deep] = { height, max, min };
        return hasChildren;
    }
    function updateUl(deep) {
        let list = getListByDeep(deep);
        if(!list) {
            return;
        }
        let ul = container.querySelectorAll('ul')[deep];
        let hasChildren = createLi(ul, list, deep);
        if(hasChildren) {
            updateUl(deep + 1);
        }
    }
    function setActive(deep, index, val) {
        if(val) {
            let list = getListByDeep(deep);
            index = list.findIndex((v)=>v.value===val);
        }
        index || (index = 0);
        container.querySelectorAll('ul')[deep].style.top = -index*sizes[deep].height+'px';
        selected[deep] = index;
    }
    function getListByDeep(deep) {
        let list = data;
        for(let i = 1; i <= deep && list; i++) {
            let index = selected[i-1] || 0;
            list = list[index].children;
        }
        return list;
    }
    function show() {
        scroll.style.visibility = 'visible';
    }
    function hide() {
        scroll.style.visibility = 'hidden';
    }
    function addAnimation(ele, deep) {
        let Y,lastY,lastTop;
        let mousedown = false;
        ele.addEventListener('mousedown', start);
        document.body.addEventListener('mouseup', end);
        document.body.addEventListener('mousemove', move);
        ele.addEventListener('touchstart', start);
        ele.addEventListener('touchend', end);
        ele.addEventListener('touchmove', move);
        ele.addEventListener('touchcancel',(ev)=>{
        });
        function start(ev) {
            switch(ev.type) {
                case 'mousedown':
                    pageY = ev.pageY;
                    mousedown = true;
                    break;
                case 'touchstart':
                    pageY = ev.touches[0].pageY;
                    break;
            }
            Y = lastY = pageY;
            lastTop = parseInt(getComputedStyle(ele).top);
        }
        function end(ev) {
            switch(ev.type) {
                case 'mouseup':
                    if(!mousedown) return;
                    mousedown = false;
                    break;
                case 'touchend':
                    break;
            }
            let newtop = lastTop + lastY - Y;
            if(newtop > sizes[deep].max) {
                newtop = sizes[deep].max;
            }
            if(newtop < sizes[deep].min) {
                newtop = sizes[deep].min;
            }
            let remain = Math.abs(newtop % sizes[deep].height);
            if(remain > sizes[deep].height / 2) {
                newtop -= sizes[deep].height - remain;
            } else {
                newtop += remain;
            }
            let active = Math.abs(newtop / sizes[deep].height);
            if(active != selected[deep]) {
                for(let i = deep + 1; i < selected.length; i++) {
                    setActive(i, 0);
                }
            }
            selected[deep] = active;
            ele.style.top = newtop+'px';
            lastTop = newtop;
            updateUl(deep+1);
        }
        function move(ev) {
            let pageY;
            switch(ev.type) {
                case 'mousemove':
                    if(!mousedown) return;
                    pageY = ev.pageY;
                    break;
                case 'touchmove':
                    pageY = ev.touches[0].pageY;
                    break;
            }
            let thisY = pageY - lastY;
            let top = parseInt(getComputedStyle(ele).top);
            ele.style.top = top+thisY+'px';
            lastY = pageY;
        }
    }
}
